package com.wmx.spring;

import cn.hutool.core.util.ObjectUtil;
import com.wmx.apachestudy.controller.ResourceController;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * 注解工具类
 *
 * @author wangMaoXiong
 * @version 1.0
 * @date 2025/9/13 下午4:24
 */
public class AnnotationUtilsTest {

    /**
     * <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType)
     * - 在指定类上寻找指定的注解，遍历其接口、注解和超类。即字类没有时，自动逐级向父类中查找。没找到时返回null.
     *
     * <A extends Annotation> A findAnnotation(Method method, @Nullable Class<A> annotationType)
     * - 在指定方法上寻找指定的注解，没找到时返回null.
     * Annotation[] getAnnotations(Method method) - 获取方法上的全部注解
     *
     * <A extends Annotation> A findAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType)
     * - 在指定字段上寻找指定的注解，没找到时返回null.
     *
     * Object getValue(Annotation annotation) - 获取注解的value属性值，没有时 或者注解为null，返回 null.
     * Object getValue(@Nullable Annotation annotation, @Nullable String attributeName) - 获取注解的指定属性值，没有时 或者注解为null，返回 null.
     * Object getDefaultValue(Annotation annotation) -获取注解的默认value值，没有时 或者注解为null，返回 null.
     * Map<String, Object> getAnnotationAttributes(Annotation annotation)  -获取注解的全部属性值
     *
     */
    @Test
    public void testFindAnnotation() throws Exception {
        RestController restController = AnnotationUtils.findAnnotation(ResourceController.class, RestController.class);
        // @org.springframework.web.bind.annotation.RestController(value=)
        System.out.println(restController);

        Method httpDelete = ResourceController.class.getMethod("httpDelete", String.class);
        DeleteMapping deleteMapping = AnnotationUtils.findAnnotation(httpDelete, DeleteMapping.class);
        // @org.springframework.web.bind.annotation.DeleteMapping(name=, value=[example/httpDelete], path=[example/httpDelete], params=[], consumes=[], headers=[], produces=[])
        System.out.println(deleteMapping);

        Field serverName = ResourceController.class.getDeclaredField("serverName");
        Value value = AnnotationUtils.findAnnotation(serverName, Value.class);
        // @org.springframework.beans.factory.annotation.Value(value=${spring.application.name:})
        System.out.println(value);

        // 安全获取注解属性值
        Object value1 = AnnotationUtils.getValue(restController);
        Object value2 = AnnotationUtils.getValue(deleteMapping);
        Object value3 = AnnotationUtils.getValue(deleteMapping, "path");
        Object value4 = AnnotationUtils.getValue(value);
        Object value5 = AnnotationUtils.getValue(value, "value");
        Object defaultValue = AnnotationUtils.getDefaultValue(value);

        System.out.println(ObjectUtil.toString(value1)); // ""
        System.out.println(ObjectUtil.toString(value2)); // [example/httpDelete]
        System.out.println(ObjectUtil.toString(value3)); // [example/httpDelete]
        System.out.println(ObjectUtil.toString(value4)); // ${spring.application.name:}
        System.out.println(ObjectUtil.toString(value5)); // ${spring.application.name:}
        System.out.println(ObjectUtil.toString(defaultValue)); // ${spring.application.name:}

        Map<String, Object> annotationAttributes = AnnotationUtils.getAnnotationAttributes(deleteMapping);
        // {name=, value=[example/httpDelete], path=[example/httpDelete], params=[], produces=[], consumes=[], headers=[]}
        System.out.println(annotationAttributes);

    }

}
